package com.ctsi.organise.service;

import com.ctsi.commons.util.StringUtil;
import com.ctsi.commons.util.UtilMisc;
import com.ctsi.commons.util.UtilValidate;
import com.ctsi.commons.util.id.UUIDGenerator;
import com.ctsi.commons.util.response.Page;
import com.ctsi.framework.common.exception.ExceptionFactory;
import com.ctsi.framework.mybatis.support.MybatisGenericDao;
import com.ctsi.organise.common.model.Organise;
import com.ctsi.organise.dto.PersonInfoDTO;
import com.ctsi.organise.dto.PersonTreeNodeDTO;
import com.ctsi.organise.dto.UserLoginTreeNodeDTO;
import com.ctsi.organise.entity.OrganiseEntity;
import com.ctsi.organise.entity.PartyEntity;
import com.ctsi.organise.entity.PersonEntity;
import com.ctsi.organise.entity.Person_Organise;
import com.ctsi.security.ISecurity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.*;


/**
 * PersonEntity Service 类
 * @author   zhangjw
 * @description  PersonEntity
 * @created	 Sun Nov 11 17:07:02 CST 2018
 */

@Repository
public class PersonEntityManager {
	private static final Logger logger=LoggerFactory.getLogger(PersonEntityManager.class);
	@Autowired
	private MybatisGenericDao dao;
	@Autowired
    private ExceptionFactory exceptionFactory;
	@Autowired
    private OrganiseEntityManager organiseEntityManager;
	@Autowired
    private Person_OrganiseManager person_organiseManager;
	@Autowired
    private ISecurity iSecurity;
	@Autowired
    private PartyEntityManager partyEntityManager;






//通过手机号查询人员是否存在
    public  Object selectPersonByPhone(String mobilePhone){
        logger.debug("selectPersonByPhone {}",mobilePhone);
        return 	 dao.queryForObject(PersonEntity.class.getName() + ".selectPersonByPhone", mobilePhone);
    }
//    查询userLogin表中是否存在该手机号
    public  Object selectUserLoginByPhone(String mobilePhone){
        logger.debug("selectUserLoginByPhone {}",mobilePhone);
        return 	 dao.queryForObject(PersonEntity.class.getName() + ".selectUserLoginByPhone", mobilePhone);
    }
	/**
	 * 添加
	 */
	public void insertPersonEntity(PersonEntity personEntity){
		if(UtilValidate.isEmpty(personEntity.getId()))
			personEntity.setId(UUIDGenerator.getId());
		logger.debug("insert {}",personEntity);
		dao.insert(personEntity);
	}
	/**
	 * 动态更新
	 */
	public int updatePersonEntityByPKSelective(PersonEntity personEntity){
		logger.debug("updateByPrimaryKeySelective {}",personEntity);
		return dao.update(PersonEntity.class.getName()+".updateByPrimaryKeySelective", personEntity);
	}
	/**
	 * 更新
	 */
	public int updatePersonEntity(PersonEntity personEntity){
		logger.debug("update {}",personEntity);
		return dao.update(personEntity);
	}


	public PersonEntity editPersonEntityById(String id){
		if(UtilValidate.isEmpty(id))
			return null;
		logger.debug("editById {}",id);
		return (PersonEntity)dao.queryForObject(PersonEntity.class.getName()+".edit", id);
	}
	/**
	 * 根据ID查找 PersonEntity对象
	 */
	public PersonEntity findPersonEntityById(String id){
		if(UtilValidate.isEmpty(id))
			return null;
		logger.debug("findById {}",id);
		return dao.get(PersonEntity.class, id);
	}
    /**selectIdByPhone
     * 根据phone查询partyId
     */
    public PersonEntity selectIdByPhone(String phone){
        if(UtilValidate.isEmpty(phone))
            return null;
        logger.debug("selectIdByPhone {}",phone);
        return (PersonEntity)dao.queryForObject(PersonEntity.class.getName()+".selectIdByPhone", phone);
    }
	/**
	 * 删除PersonEntity对象
	 */
	public int removePersonEntity(String id){
		if(UtilValidate.isNotEmpty(id)){
            // TODO: 完成物理删除
		   // person_organiseManager.removePerson_Organise();
            return dao.delete(PersonEntity.class.getName()+".delete", id);
        }
		return 0;
	}

	/**
	 * 详细页查询
	 */
	public PersonEntity findByDetail(String id){
		return (PersonEntity)dao.queryForObject(PersonEntity.class.getName()+".findByDetail",id);
	}
	/**
	 * 多条件查询结果
	 */
	public Page<PersonInfoDTO> findByMulitCondition(Map<String,Object> param , int start , int pageSize){
		logger.debug("findByMulitCondition {}",param);
		if(pageSize<0||pageSize>2000)
			pageSize=Page.DEFAULT_PAGE_SIZE;
		if(start!=-1)
			return dao.queryPage(PersonEntity.class.getName()+".selectMulitCondition", param, start, pageSize);
		else{
			throw new RuntimeException("参数不正确 !!");
		}
	}
	/**
	 * 多条件查询结果不分页
	 */
	public List<PersonEntity> find(Map<String,Object> map){
		logger.debug("find {}",map);
		return (List<PersonEntity>)dao.queryForList(PersonEntity.class.getName()+".selectByMap",map);
	}

    /**
     * 根据partyid获取所属组织
     * @param personId
     * @return
     */
    public List<Organise> getBelongOrgan(String personId) {
        if (UtilValidate.isEmpty(personId)) {
            logger.error("personId is null");
            throw new IllegalArgumentException("personId is null");
        }
        return (List<Organise>) dao.queryForList(OrganiseEntity.class.getName() + ".getBelongOrgan", personId);
    }

    /**
     * 获取人员默认部门
     * @param personId
     * @return
     */
    public OrganiseEntity getUserDefaultOrgan(String personId){
        if (UtilValidate.isEmpty(personId)) {
            logger.error("personId is null");
            throw new IllegalArgumentException("personId is null");
        }
        return (OrganiseEntity) dao.queryForObject(OrganiseEntity.class.getName() + ".getDefaultOrgan", personId);
    }

    /**
     * 验证人员是否在该组织中，
     * @param organId 组织ID
     * @param personId
     * @return 存在返回true 不存在抛出异常
     */
    private boolean isAddValid(String organId,String personId){
        Map<String, String> map = new HashMap<String, String>();
        map.put("organId", organId);
        map.put("personId", personId);
        long count = (Long) dao.queryForObject(Person_Organise.class.getName() + ".selectMap_count", map);
        if (count != 0){
            logger.error("organId:{} already contains person personId:{}",organId,   personId);
            exceptionFactory.throwDefinedException("30004");
            return false;
        } else {
            return true;
        }
    }

    public int findMaxOrderInPerson_Organ(String organId){
        Integer order = (Integer) dao.queryForObject(Person_Organise.class.getName()+".findMaxOrderInPerson_Organ", organId);

        return order == null? 0: order;
    }

    /**
     * 根据人员id和部门id获得层级结构id
     *
     * @param personId
     * @param partyId 直接部门ID
     * @return
     */
    public String getPersonStructId(String personId, String partyId) {
        Map<String, Object> parameterObject = new HashMap<>();
        parameterObject.put("personId", personId);
        parameterObject.put("organId", partyId);
        parameterObject.put("structLevel", Person_Organise.PERSON_ORGANISE_STRUCTLEVEL_YES);
        List<String> listRes = (List<String>) dao.queryForList(Person_Organise.class.getName() + ".getPersonStructId", parameterObject);
        if (UtilValidate.isNotEmpty(listRes)){
            if(listRes.size()==1){
                logger.info("获得人员当前部门所在层级关系数据  structId={} , personId={} ,partyId={}", StringUtil.join(listRes, ","),personId,partyId);
                return listRes.get(0);
            }else{
                logger.error("获得人员当前部门所在层级关系时得到多条数据   structId={}  personId={} ,partyId={}",StringUtil.join(listRes, ","),personId,partyId);
                throw new RuntimeException(new StringBuffer("获得人员当前部门所在层级关系时获得多条数据 structId=").append(StringUtil.join(listRes, ",")).append(" , personId=").append(personId).append(" ,  partyId=").append(partyId).toString());
            }
        }
        logger.error("没有获得人员当前部门所在层级关系   personId{} ,partyId{} ",personId,partyId);
        return null;
    }

    public void savePersonToOrgan(String organId,String personId,int isDefaultOrgan,boolean publishEvent){
        if (isAddValid(organId, personId)) {
            int order = findMaxOrderInPerson_Organ(organId);
            String structId = this.getPersonStructId(personId,organId );
            if(UtilValidate.isNotEmpty(structId)){
                // 此处永远不会执行 暂时这样
                Person_Organise personOrgan = new Person_Organise();
                personOrgan.setPersonId(personId);
                personOrgan.setOrganId(organId);
                personOrgan.setId(UUIDGenerator.getId());
                personOrgan.setOrderNo(order);
                personOrgan.setJoinTime(System.currentTimeMillis());
                personOrgan.setStructId(structId);
                dao.insert(personOrgan);
            }else if ( UtilValidate.isEmpty(structId)){
                /**
                 * 如果经过以上两个方法仍旧获得不到structId则表示是添加的人员没有该ID则使用生成该ID的添加人员组织关系
                 */
                structId = UUIDGenerator.getId();
                Organise organise = null;
                int level=0;
                LOOP: do {
                    String organIdCondation = organId;
                    if (organise != null) {
                        organIdCondation = organise.getParentId();
                    }
                    organise = organiseEntityManager.findOrganiseEntityById(organIdCondation);
                    if (organise == null) {
                        logger.debug("get the organise is null");
                        break LOOP;
                    }
                    Person_Organise personOrgan = new Person_Organise();
                    personOrgan.setPersonId(personId);
                    personOrgan.setOrganId(organise.getPartyId());
                    personOrgan.setId(UUIDGenerator.getId());
                    personOrgan.setOrderNo(order);
                    personOrgan.setJoinTime(System.currentTimeMillis());
                    personOrgan.setStructId(structId);
                    personOrgan.setPartyTypeId(organise.getPartyTypeId());
                    personOrgan.setIsDefaultOrgan(1);
                    if (organise.getPartyId().equals(organId)) {
                        personOrgan.setStructLevel(Person_Organise.PERSON_ORGANISE_STRUCTLEVEL_YES);
                    } else {
                        personOrgan.setStructLevel(level);
                    }

                    dao.insert(personOrgan);
                    level++;
                    if (UtilValidate.isEmpty(organise.getParentId()) || IOrganiseService.DEFAULT_ORGAN_ROOT.equals(organise.getParentId())) {
                        logger.debug("get the top organise");
                        break LOOP;
                    }
                } while (true);
            }
        }
    }


    /**
     *  人员树，懒加载树
     * @param parentId
     * @return
     */
    public List<PersonTreeNodeDTO> findChildNodeByParentId(String userloginId,String parentId,String tenementId){
//        if (UtilValidate.isEmpty(tenementId)){
//            logger.warn("tenement id is null,so return empty data List");
//            return Collections.emptyList();
//        }
        if (!iSecurity.isControl(userloginId,"organChain","SELECT")) {
            return (List<PersonTreeNodeDTO>) dao.queryForList(PersonEntity.class.getName()+".selectPersonTree", UtilMisc.toMap("parentId",parentId,"tenementId",tenementId));
        }
        Set<String> dataObjectIds = iSecurity.findDataObjectIds(userloginId,"organChain","SELECT");
        if (UtilValidate.isEmpty(dataObjectIds)) {
            return Collections.emptyList();
        }
        return (List<PersonTreeNodeDTO>) dao.queryForList(PersonEntity.class.getName()+".selectPersonTree",UtilMisc.toMap("parentId",parentId,"tenementId",tenementId,"dataObjectIds",dataObjectIds));
    }

    /**
     * 登陆用户树，懒加载
     * @param userloginId
     * @param parentId
     * @return
     */
    public List<UserLoginTreeNodeDTO> findChildUserLoginNodeByParentId(String userloginId,String parentId){
        if (!iSecurity.isControl(userloginId,"organChain","SELECT")) {
            return (List<UserLoginTreeNodeDTO>) dao.queryForList(PersonEntity.class.getName()+".userLoginTree", UtilMisc.toMap("parentId",parentId));
        }
        Set<String> dataObjectIds = iSecurity.findDataObjectIds(userloginId,"organChain","SELECT");
        if (UtilValidate.isEmpty(dataObjectIds)) {
            return Collections.emptyList();
        }
        return (List<UserLoginTreeNodeDTO>) dao.queryForList(PersonEntity.class.getName()+".userLoginTree",UtilMisc.toMap("parentId",parentId,"dataObjectIds",dataObjectIds));

    }

    public void removePersonFromOrgan(String personId,String organId){
        String structId = this.getPersonStructId(personId,organId);
        this.dao.remove(Person_Organise.class.getName()+".removeByStructId",structId);
        logger.warn("user {} leave from organ: {}",personId,organId);
    }

    /**
     * 人员移动
     * @param personId
     * @param srcOrganId
     * @param destOrganId
     */
    public void personMove(String personId,String srcOrganId,String destOrganId){
        removePersonFromOrgan(personId,srcOrganId);
        savePersonToOrgan(destOrganId,personId,1,true);
        // 更新人员dataObjectId
        Organise org = organiseEntityManager.findOrganiseEntityById(destOrganId);
        PartyEntity partyEntity = new PartyEntity();
        partyEntity.setDataObjectId(org.getDataObjectId());
        partyEntity.setId(personId);
        partyEntityManager.updatePartyEntityByPKSelective(partyEntity);
        logger.warn("move person {} from {} to {}",personId,srcOrganId,destOrganId);
    }

}
